home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / MFC / src / oleunk.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  12.9 KB  |  470 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_OLE_SEG
  14. #pragma code_seg(AFX_OLE_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // Debug helpers
  26.  
  27. #ifdef _DEBUG
  28. // Helper for converting IID into useful string.  Only for debugging.
  29. LPCTSTR AFXAPI AfxGetIIDString(REFIID iid)
  30. {
  31.     static TCHAR szUnfamiliar[80];
  32.     TCHAR szByte[3];
  33.  
  34.     struct IID_ENTRY
  35.     {
  36.         const IID* piid;
  37.         LPCTSTR lpszName;
  38.     };
  39.  
  40. #define MAKE_IID_ENTRY(name) { &name, _T(#name) }
  41.  
  42.     static const IID_ENTRY iidNameTable[] =
  43.     {
  44.         MAKE_IID_ENTRY(IID_IAdviseSink),
  45.         MAKE_IID_ENTRY(IID_IAdviseSink2),
  46.         MAKE_IID_ENTRY(IID_IBindCtx),
  47.         MAKE_IID_ENTRY(IID_IClassFactory),
  48. #if !defined(_WIN32_WCE)
  49.         MAKE_IID_ENTRY(IID_IContinueCallback),
  50.         MAKE_IID_ENTRY(IID_IEnumOleDocumentViews),
  51.         MAKE_IID_ENTRY(IID_IOleCommandTarget),
  52.         MAKE_IID_ENTRY(IID_IOleDocument),
  53.         MAKE_IID_ENTRY(IID_IOleDocumentSite),
  54.         MAKE_IID_ENTRY(IID_IOleDocumentView),
  55.         MAKE_IID_ENTRY(IID_IPrint),
  56. #endif // _WIN32_WCE
  57.         MAKE_IID_ENTRY(IID_IDataAdviseHolder),
  58.         MAKE_IID_ENTRY(IID_IDataObject),
  59.         MAKE_IID_ENTRY(IID_IDebug),
  60.         MAKE_IID_ENTRY(IID_IDebugStream),
  61.         MAKE_IID_ENTRY(IID_IDfReserved1),
  62.         MAKE_IID_ENTRY(IID_IDfReserved2),
  63.         MAKE_IID_ENTRY(IID_IDfReserved3),
  64.         MAKE_IID_ENTRY(IID_IDispatch),
  65.         MAKE_IID_ENTRY(IID_IDropSource),
  66.         MAKE_IID_ENTRY(IID_IDropTarget),
  67.         MAKE_IID_ENTRY(IID_IEnumCallback),
  68.         MAKE_IID_ENTRY(IID_IEnumFORMATETC),
  69.         MAKE_IID_ENTRY(IID_IEnumGeneric),
  70.         MAKE_IID_ENTRY(IID_IEnumHolder),
  71.         MAKE_IID_ENTRY(IID_IEnumMoniker),
  72.         MAKE_IID_ENTRY(IID_IEnumOLEVERB),
  73.         MAKE_IID_ENTRY(IID_IEnumSTATDATA),
  74.         MAKE_IID_ENTRY(IID_IEnumSTATSTG),
  75.         MAKE_IID_ENTRY(IID_IEnumString),
  76.         MAKE_IID_ENTRY(IID_IEnumUnknown),
  77.         MAKE_IID_ENTRY(IID_IEnumVARIANT),
  78. //      MAKE_IID_ENTRY(IID_IExternalConnection),
  79.         MAKE_IID_ENTRY(IID_IInternalMoniker),
  80.         MAKE_IID_ENTRY(IID_ILockBytes),
  81.         MAKE_IID_ENTRY(IID_IMalloc),
  82.         MAKE_IID_ENTRY(IID_IMarshal),
  83. #if !defined(_WIN32_WCE)
  84.         MAKE_IID_ENTRY(IID_IMessageFilter),
  85. #endif // _WIN32_WCE
  86.         MAKE_IID_ENTRY(IID_IMoniker),
  87.         MAKE_IID_ENTRY(IID_IOleAdviseHolder),
  88.         MAKE_IID_ENTRY(IID_IOleCache),
  89.         MAKE_IID_ENTRY(IID_IOleCache2),
  90.         MAKE_IID_ENTRY(IID_IOleCacheControl),
  91.         MAKE_IID_ENTRY(IID_IOleClientSite),
  92.         MAKE_IID_ENTRY(IID_IOleContainer),
  93.         MAKE_IID_ENTRY(IID_IOleInPlaceActiveObject),
  94.         MAKE_IID_ENTRY(IID_IOleInPlaceFrame),
  95.         MAKE_IID_ENTRY(IID_IOleInPlaceObject),
  96.         MAKE_IID_ENTRY(IID_IOleInPlaceSite),
  97.         MAKE_IID_ENTRY(IID_IOleInPlaceUIWindow),
  98.         MAKE_IID_ENTRY(IID_IOleItemContainer),
  99.         MAKE_IID_ENTRY(IID_IOleLink),
  100.         MAKE_IID_ENTRY(IID_IOleManager),
  101.         MAKE_IID_ENTRY(IID_IOleObject),
  102.         MAKE_IID_ENTRY(IID_IOlePresObj),
  103.         MAKE_IID_ENTRY(IID_IOleWindow),
  104.         MAKE_IID_ENTRY(IID_IPSFactory),
  105.         MAKE_IID_ENTRY(IID_IParseDisplayName),
  106.         MAKE_IID_ENTRY(IID_IPersist),
  107.         MAKE_IID_ENTRY(IID_IPersistFile),
  108.         MAKE_IID_ENTRY(IID_IPersistStorage),
  109.         MAKE_IID_ENTRY(IID_IPersistStream),
  110.         MAKE_IID_ENTRY(IID_IProxyManager),
  111.         MAKE_IID_ENTRY(IID_IRootStorage),
  112.         MAKE_IID_ENTRY(IID_IRpcChannel),
  113.         MAKE_IID_ENTRY(IID_IRpcProxy),
  114.         MAKE_IID_ENTRY(IID_IRpcStub),
  115.         MAKE_IID_ENTRY(IID_IRunnableObject),
  116.         MAKE_IID_ENTRY(IID_IRunningObjectTable),
  117.         MAKE_IID_ENTRY(IID_IStdMarshalInfo),
  118.         MAKE_IID_ENTRY(IID_IStorage),
  119.         MAKE_IID_ENTRY(IID_IStream),
  120.         MAKE_IID_ENTRY(IID_IStubManager),
  121.         MAKE_IID_ENTRY(IID_IUnknown),
  122.         MAKE_IID_ENTRY(IID_IViewObject),
  123.         MAKE_IID_ENTRY(IID_IViewObject2),
  124.         MAKE_IID_ENTRY(IID_NULL),
  125.     };
  126. #undef MAKE_IID_ENTRY
  127.  
  128.     // look for it in the table
  129.     for (int i = 0; i < _countof(iidNameTable); i++)
  130.     {
  131.         if (iid == *iidNameTable[i].piid)
  132.             return iidNameTable[i].lpszName;
  133.     }
  134.     // if we get here, it is some IID_ we haven't heard of...
  135.  
  136.     wsprintf(szUnfamiliar, _T("%8.8X-%4.4X-%4.4X-"),
  137.         iid.Data1, iid.Data2, iid.Data3);
  138.     for (int nIndex = 0; nIndex < 8; nIndex++)
  139.     {
  140.         wsprintf(szByte, _T("%2.2X"), iid.Data4[nIndex]);
  141.         lstrcat(szUnfamiliar, szByte);
  142.     }
  143.  
  144.     return szUnfamiliar;
  145. }
  146. #endif
  147.  
  148. /////////////////////////////////////////////////////////////////////////////
  149. // Component object model helpers
  150.  
  151. /////////////////////////////////////////////////////////////////////////////
  152. // IUnknown client helpers
  153.  
  154. LPUNKNOWN AFXAPI _AfxQueryInterface(LPUNKNOWN lpUnknown, REFIID iid)
  155. {
  156.     ASSERT(lpUnknown != NULL);
  157.  
  158.     LPUNKNOWN lpW = NULL;
  159.     if (lpUnknown->QueryInterface(iid, (LPLP)&lpW) != S_OK)
  160.         return NULL;
  161.  
  162.     return lpW;
  163. }
  164.  
  165. DWORD AFXAPI _AfxRelease(LPUNKNOWN* lplpUnknown)
  166. {
  167.     ASSERT(lplpUnknown != NULL);
  168.     if (*lplpUnknown != NULL)
  169.     {
  170.         DWORD dwRef = (*lplpUnknown)->Release();
  171.         *lplpUnknown = NULL;
  172.         return dwRef;
  173.     }
  174.     return 0;
  175. }
  176.  
  177. #define GetInterfacePtr(pTarget, pEntry) \
  178.     ((LPUNKNOWN)((BYTE*)pTarget + pEntry->nOffset))
  179.  
  180. #define GetAggregatePtr(pTarget, pEntry) \
  181.     (*(LPUNKNOWN*)((BYTE*)pTarget + pEntry->nOffset))
  182.  
  183. /////////////////////////////////////////////////////////////////////////////
  184. // CCmdTarget interface map implementation
  185.  
  186. // support for aggregation
  187. class CInnerUnknown : public IUnknown
  188. {
  189. public:
  190.     STDMETHOD_(ULONG, AddRef)();
  191.     STDMETHOD_(ULONG, Release)();
  192.     STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj);
  193. };
  194.  
  195. // calling this function enables an object to be aggregatable
  196. void CCmdTarget::EnableAggregation()
  197. {
  198.     // construct an CInnerUnknown just to get to the vtable
  199.     CInnerUnknown innerUnknown;
  200.  
  201.     // copy the vtable & make sure initialized
  202.     ASSERT(sizeof(m_xInnerUnknown) == sizeof(CInnerUnknown));
  203.     m_xInnerUnknown = *(DWORD*)&innerUnknown;
  204. }
  205.  
  206. DWORD CCmdTarget::ExternalAddRef()
  207. {
  208.     // delegate to controlling unknown if aggregated
  209.     if (m_pOuterUnknown != NULL)
  210.         return m_pOuterUnknown->AddRef();
  211.  
  212.     return InternalAddRef();
  213. }
  214.  
  215. DWORD CCmdTarget::InternalRelease()
  216. {
  217.     ASSERT(GetInterfaceMap() != NULL);
  218.  
  219.     if (m_dwRef == 0)
  220.         return 0;
  221.  
  222.     LONG lResult = InterlockedDecrement(&m_dwRef);
  223.     if (lResult == 0)
  224.     {
  225.         AFX_MANAGE_STATE(m_pModuleState);
  226.         OnFinalRelease();
  227.     }
  228.     return lResult;
  229. }
  230.  
  231. DWORD CCmdTarget::ExternalRelease()
  232. {
  233.     // delegate to controlling unknown if aggregated
  234.     if (m_pOuterUnknown != NULL)
  235.         return m_pOuterUnknown->Release();
  236.  
  237.     return InternalRelease();
  238. }
  239.  
  240. // special QueryInterface used in implementation (does not AddRef)
  241. LPUNKNOWN CCmdTarget::GetInterface(const void* iid)
  242. {
  243.     // allow general hook first chance
  244.     LPUNKNOWN lpUnk;
  245.     if ((lpUnk = GetInterfaceHook(iid)) != NULL)
  246.         return lpUnk;
  247.  
  248.     const AFX_INTERFACEMAP* pMap = GetInterfaceMap();
  249.     ASSERT(pMap != NULL);
  250.     DWORD lData1 = ((IID*)iid)->Data1;
  251.  
  252.     // IUnknown is a special case since nobody really implements *only* it!
  253.     BOOL bUnknown = ((DWORD*)&IID_IUnknown)[0] == lData1 &&
  254.         ((DWORD*)iid)[1] == ((DWORD*)&IID_IUnknown)[1] &&
  255.         ((DWORD*)iid)[2] == ((DWORD*)&IID_IUnknown)[2] &&
  256.         ((DWORD*)iid)[3] == ((DWORD*)&IID_IUnknown)[3];
  257.     if (bUnknown)
  258.     {
  259.         do
  260.         {
  261.             const AFX_INTERFACEMAP_ENTRY* pEntry = pMap->pEntry;
  262.             ASSERT(pEntry != NULL);
  263.             while (pEntry->piid != NULL)
  264.             {
  265.                 // check INTERFACE_ENTRY macro
  266.                 LPUNKNOWN lpUnk = GetInterfacePtr(this, pEntry);
  267.  
  268.                 // check vtable pointer (can be NULL)
  269.                 if (*(DWORD*)lpUnk != 0)
  270.                     return lpUnk;
  271.  
  272.                 // entry did not match -- keep looking
  273.                 ++pEntry;
  274.             }
  275. #ifdef _AFXDLL
  276.         } while ((pMap = (*pMap->pfnGetBaseMap)()) != NULL);
  277. #else
  278.         } while ((pMap = pMap->pBaseMap) != NULL);
  279. #endif
  280.  
  281.         // interface ID not found, fail the call
  282.         return NULL;
  283.     }
  284.  
  285.     // otherwise, walk the interface map to find the matching IID
  286.     do
  287.     {
  288.         const AFX_INTERFACEMAP_ENTRY* pEntry = pMap->pEntry;
  289.         ASSERT(pEntry != NULL);
  290.         while (pEntry->piid != NULL)
  291.         {
  292.             if (((DWORD*)pEntry->piid)[0] == lData1 &&
  293.                 ((DWORD*)pEntry->piid)[1] == ((DWORD*)iid)[1] &&
  294.                 ((DWORD*)pEntry->piid)[2] == ((DWORD*)iid)[2] &&
  295.                 ((DWORD*)pEntry->piid)[3] == ((DWORD*)iid)[3])
  296.             {
  297.                 // check INTERFACE_ENTRY macro
  298.                 LPUNKNOWN lpUnk = GetInterfacePtr(this, pEntry);
  299.  
  300.                 // check vtable pointer (can be NULL)
  301.                 if (*(DWORD*)lpUnk != 0)
  302.                     return lpUnk;
  303.             }
  304.  
  305.             // entry did not match -- keep looking
  306.             ++pEntry;
  307.         }
  308. #ifdef _AFXDLL
  309.     } while ((pMap = (*pMap->pfnGetBaseMap)()) != NULL);
  310. #else
  311.     } while ((pMap = pMap->pBaseMap) != NULL);
  312. #endif
  313.  
  314.     // interface ID not found, fail the call
  315.     return NULL;
  316. }
  317.  
  318. LPUNKNOWN CCmdTarget::QueryAggregates(const void* iid)
  319. {
  320.     const AFX_INTERFACEMAP* pMap = GetInterfaceMap();
  321.     ASSERT(pMap != NULL);
  322.  
  323.     // walk the Interface map to call aggregates
  324.     do
  325.     {
  326.         const AFX_INTERFACEMAP_ENTRY* pEntry = pMap->pEntry;
  327.         // skip non-aggregate entries
  328.         ASSERT(pEntry != NULL);
  329.         while (pEntry->piid != NULL)
  330.             ++pEntry;
  331.  
  332.         // call QueryInterface for each aggregate entry
  333.         while (pEntry->nOffset != (size_t)-1)
  334.         {
  335.             LPUNKNOWN lpQuery = GetAggregatePtr(this, pEntry);
  336.             // it is ok to have aggregate but not created yet
  337.             if (lpQuery != NULL)
  338.             {
  339.                 LPUNKNOWN lpUnk = NULL;
  340.                 if (lpQuery->QueryInterface(*(IID*)iid, (LPLP)&lpUnk)
  341.                     == S_OK && lpUnk != NULL)
  342.                 {
  343.                     // QueryInterface successful...
  344.                     return lpUnk;
  345.                 }
  346.             }
  347.  
  348.             // entry did not match -- keep looking
  349.             ++pEntry;
  350.         }
  351. #ifdef _AFXDLL
  352.     } while ((pMap = (*pMap->pfnGetBaseMap)()) != NULL);
  353. #else
  354.     } while ((pMap = pMap->pBaseMap) != NULL);
  355. #endif
  356.  
  357.     // interface ID not found, fail the call
  358.     return NULL;
  359. }
  360.  
  361. // real implementation of QueryInterface
  362. DWORD CCmdTarget::InternalQueryInterface(const void* iid, LPVOID* ppvObj)
  363. {
  364.     // check local interfaces
  365.     if ((*ppvObj = GetInterface(iid)) != NULL)
  366.     {
  367.         // interface was found -- add a reference
  368.         ExternalAddRef();
  369.         return S_OK;
  370.     }
  371.  
  372.     // check aggregates
  373.     if ((*ppvObj = QueryAggregates(iid)) != NULL)
  374.         return S_OK;
  375.  
  376.     // interface ID not found, fail the call
  377.     return (DWORD)E_NOINTERFACE;
  378. }
  379.  
  380. // QueryInterface that is exported to normal clients
  381. DWORD CCmdTarget::ExternalQueryInterface(const void* iid,
  382.     LPVOID* ppvObj)
  383. {
  384.     // delegate to controlling unknown if aggregated
  385.     if (m_pOuterUnknown != NULL)
  386.         return m_pOuterUnknown->QueryInterface(*(IID*)iid, ppvObj);
  387.  
  388.     return InternalQueryInterface(iid, ppvObj);
  389. }
  390.  
  391. /////////////////////////////////////////////////////////////////////////////
  392. // Inner IUnknown implementation (for aggregation)
  393.  
  394. STDMETHODIMP_(ULONG) CInnerUnknown::AddRef()
  395. {
  396.     METHOD_PROLOGUE_(CCmdTarget, InnerUnknown)
  397.     return pThis->InternalAddRef();
  398. }
  399.  
  400. STDMETHODIMP_(ULONG) CInnerUnknown::Release()
  401. {
  402.     METHOD_PROLOGUE(CCmdTarget, InnerUnknown)
  403.     return pThis->InternalRelease();
  404. }
  405.  
  406. STDMETHODIMP CInnerUnknown::QueryInterface(REFIID iid, LPVOID* ppvObj)
  407. {
  408.     METHOD_PROLOGUE_(CCmdTarget, InnerUnknown)
  409.  
  410.     if (iid == IID_IUnknown)
  411.     {
  412.         // QueryInterface on inner IUnknown for IID_IUnknown must
  413.         //  return inner IUnknown.
  414.         pThis->InternalAddRef();
  415.         *ppvObj = this;
  416.         return S_OK;
  417.     }
  418.     return pThis->InternalQueryInterface(&iid, ppvObj);
  419. }
  420.  
  421. /////////////////////////////////////////////////////////////////////////////
  422. // other helper functions
  423.  
  424. // ExternalDisconnect is used to remove RPC connections in destructors.  This
  425. //  insures that no RPC calls will go to the object after it has been
  426. //  deleted.
  427. void CCmdTarget::ExternalDisconnect()
  428. {
  429.     if (m_dwRef == 0)   // already in disconnected state?
  430.         return;
  431.  
  432.     // get IUnknown pointer for the object
  433.     LPUNKNOWN lpUnknown = (LPUNKNOWN)GetInterface(&IID_IUnknown);
  434.     ASSERT(lpUnknown != NULL);
  435.  
  436.     // disconnect the object
  437.     InterlockedIncrement(&m_dwRef);  // protect object from destruction
  438.     WCE_FCTN(CoDisconnectObject)(lpUnknown, 0);
  439.     m_dwRef = 0;    // now in disconnected state
  440. }
  441.  
  442. // GetControllingUnknown is used when creating aggregate objects,
  443. //  usually from OnCreateAggregates.  The outer, or controlling, unknown
  444. //  is one of the parameters to CoCreateInstance and other OLE creation
  445. //  functions which support aggregation.
  446. LPUNKNOWN CCmdTarget::GetControllingUnknown()
  447. {
  448.     if (m_pOuterUnknown != NULL)
  449.         return m_pOuterUnknown; // aggregate of m_pOuterUnknown
  450.  
  451.     LPUNKNOWN lpUnknown = (LPUNKNOWN)GetInterface(&IID_IUnknown);
  452.     return lpUnknown;   // return our own IUnknown implementation
  453. }
  454.  
  455. /////////////////////////////////////////////////////////////////////////////
  456. // Inline function declarations expanded out-of-line
  457.  
  458. #ifndef _AFX_ENABLE_INLINES
  459.  
  460. // expand inlines for OLE general APIs
  461. static char _szAfxOleInl[] = "afxole.inl";
  462. #undef THIS_FILE
  463. #define THIS_FILE _szAfxOleInl
  464. #define _AFXDISP_INLINE
  465. #include "afxole.inl"
  466.  
  467. #endif //!_AFX_ENABLE_INLINES
  468.  
  469. /////////////////////////////////////////////////////////////////////////////
  470.